package cn.hhz.charging.device.service.impl;

import cn.hhz.charging.common.pojo.param.GunStatusUpdateParam;
import cn.hhz.charging.common.pojo.vo.StationInfoVO;
import cn.hhz.charging.device.pojo.po.StationPO;
import cn.hhz.charging.device.service.DeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;


@Slf4j
@Service
public class DeviceServiceImpl implements DeviceService {

    @Override
    public StationInfoVO getStationInfo(Integer gunId) {
        StationInfoVO stationInfoVO = new StationInfoVO();
        stationInfoVO.setStationId(777);
        stationInfoVO.setOperatorId(111);
        return stationInfoVO;
    }

    @Override
    public Boolean updateGunStatus(GunStatusUpdateParam gunStatusUpdateParam) {
        return true;
    }

    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    @Autowired
    private RedisTemplate<String, StationPO> redisTemplateForStationPo;

    @Autowired
    private RedisTemplate<String, Map<String,Object>> redisTemplateForStationPoHash;


    @Override
    public List<StationInfoVO> getNearStation(Double longitude, Double latitude, Double radius) {

        BoundGeoOperations<String, Serializable> stations =
                redisTemplate.boundGeoOps("stations");
        //通过用户的经纬度构建RedisGEO的Point 用户的位置 是一个点
        Point userPoint = new Point(longitude,latitude);
        //通过用户传入的查找距离,理解为圆的半径  打车车 千米公里 ,步行 米
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        //通过点和半径 画圆
        Circle circle = new Circle(userPoint,distance);

        //设置参数
        RedisGeoCommands.GeoRadiusCommandArgs args =
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        //设置参数,告诉Redis查询的时候返回距离 距离是动态,用户当时在不同的点查询的,距离会不一样
        args.includeDistance();
        //设置参数,告诉Redis查询的时候返回经纬度,为了方便地图绘制
        args.includeCoordinates();
        GeoResults<RedisGeoCommands.GeoLocation<Serializable>> geoResult =
                stations.radius(circle, args);
        log.debug("查询结果:{}",geoResult);
        List<StationInfoVO> stationInfoVOS = new ArrayList<>();
        for (GeoResult<RedisGeoCommands.GeoLocation<Serializable>> result : geoResult) {
            //Content 里name属性,缓存预热时 保存Point map的key 站点id
            Serializable name = result.getContent().getName();
            //充电站和入参用户位置的距离
            double value = result.getDistance().getValue();
            //充电站的经纬度 点
            Point point = result.getContent().getPoint();


            StationInfoVO stationInfoVO = new StationInfoVO();
            stationInfoVO.setLongitude(point.getX());
            stationInfoVO.setLatitude(point.getY());
            stationInfoVO.setDistance(value);
            //通过String类型获取场站信息
            StationPO stationPO = getStationInfoByString(String.valueOf(name));
            //通过Hash类型获取场站信息
            //StationPO stationPO = getStationInfoByHash(String.valueOf(name));
            if (stationPO != null) {
                stationInfoVO.setStationName(stationPO.getStationName());
            }
            stationInfoVO.setStationId(Integer.valueOf(String.valueOf(name)));
            stationInfoVOS.add(stationInfoVO);
        }
        return stationInfoVOS;
    }



    /**
     * 获取Hash类型的场站信息
     * @param id
     * @return
     */
    private StationPO getStationInfoByHash(String id){
        String key = "station_info_hash_" + id;
        HashOperations<String, Object, Object> hash =
                redisTemplateForStationPoHash.opsForHash();
        Map<Object, Object> entries = hash.entries(key);
        StationPO stationPO  = new StationPO();
        stationPO.setStationName(String.valueOf(entries.get("name")));

        Map<String,Map<String,String>> map = new HashMap<>();
        Map<String,String> small = new HashMap<>();
        small.put("smallKey","jack");
        map.put("bigKey",small);
        //java
        //1 先通过外面的key 大key 获取 小map
        Map<String, String> smallMap = map.get("bigKey");
        //2 通过里面的key 小key 获取小map 小key对应的值
        String s = smallMap.get("smallKey");

        //Redis
        // 1 一步搞定 通过大key和小key直接获取小key的值
        //String name = hash.get("bigKey", "smallKey");
        Object o = hash.get(key, "name");

        hash.put("bigKey","smallKey","new-name");

        return stationPO;
    }


    /**
     * 获取String类型的场站信息
     * @param id
     * @return
     */
    private StationPO getStationInfoByString(String id){
        String key = "station_info_string_" + id;
        ValueOperations<String, StationPO> str = redisTemplateForStationPo.opsForValue();
        StationPO stationPO = str.get(key);
        return stationPO;
    }
}
